package com.study.example.study.test;

import cn.hutool.core.lang.Console;
import com.google.common.cache.LoadingCache;
import lombok.*;

import java.time.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 测试类
 *
 * @author ErYang
 */
public final class MapTest2 {

    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>(16);
        List<String> mapKeyList = new ArrayList<>(map.keySet());
        // []
        Console.log("mapKeyList={}", mapKeyList);

        map.put("A", "B");
        map.put("A", "C");
        map.put("B", "C");
        mapKeyList = map.keySet().stream().collect(Collectors.toList());
        // [A, B]
        Console.log("mapKeyList={}", mapKeyList);

        map.clear();
        List<String> mapValueList = new ArrayList<>(map.values());
        // []
        Console.log("mapValueList={}", mapValueList);

        map.put("A", "B");
        map.put("A", "C");
        map.put("B", "C");
        mapValueList = map.values().stream().collect(Collectors.toList());
        // [C, C]
        Console.log("mapValueList={}", mapValueList);


        // 当天 00:00:00
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        // 当天 23:59:59
        LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        // 转为毫秒
        long milliseconds = todayEnd.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        Console.log("todayEnd={}", milliseconds);
         milliseconds = Instant.now().toEpochMilli();
        Console.log("now={}", milliseconds);
        // 转为毫秒
         milliseconds = Duration.between(LocalDateTime.now(),todayEnd).toMillis();
        Console.log("相差={}", milliseconds);
    }

    public LoadingCache<Integer, String> createGuavaCache() {
        //设置合理的 expireAfterWrite 和 refreshAfterWrite 时间来保证缓存不会被瞬间击垮。根据合理的场景设置合理的参数。

        // 比如 expireAfterWrite=60 和 refreshAfterWrite=30，保证每隔 30 秒刷新⼀次数据。但是超过 60 秒⼀直没有访问量，突然间访问，还是会触发 load 操作。


//        expireAfterWrite 是为了保证在很久没有访问量，⾸次访问不再访问旧值。⽐如已经间隔⼀天，首次访问希望获取最新值，而不是先获取旧值再去刷新新值，这种就可⽤通过设置expireAfterWrite来保证。
//
//        其实如果极端情况下，即新旧值基本不会变更的，直接不采⽤ expireAfterWrite，⽽直接采⽤ refreshAfterWrite 来执⾏ load 也是可以的，性能会更优
//
//        使用注意：请注意：如果每次去取值的时候希望走load方法 要使用get() 而不是getIfPresent()
//        但是get方法会抛出异常需要捕捉处理，getIfPersent如果不存在就返回空值，但是不会走load方法去主动填充缓存。


//        return CacheBuilder.newBuilder()
//                // 设置并发级别为 cpu 核心数，默认为4
//                .concurrencyLevel(Runtime.getRuntime().availableProcessors())
//                // 设置写缓存后10秒钟后过期
//                .expireAfterWrite(10, TimeUnit.SECONDS)
//                .refreshAfterWrite(8, TimeUnit.SECONDS)
//                        // 设置缓存容器的初始容量为8
//                        .initialCapacity(8)
//                        // 设置缓存最大容量为10，超过10之后就会按照LRU最近虽少使用算法来移除缓存项
//                        .maximumSize(10)
//                        // 设置统计缓存的各种统计信息（生产坏境关闭）
//                        .recordStats()
//                        // 设置缓存的移除通知
//                        .removalListener(new RemovalListener<Object, Object>() {
//                            @Override
//                            public void onRemoval(RemovalNotification<Object, Object> notification) {
//                                System.out.println(notification.getKey() + " was removed, cause is " + notification.getCause());
//                            }
//                        })
//                        // 指定CacheLoader，在缓存不存在时通过CacheLoader的实现自动加载缓存
//                        .build(new CacheLoader<Integer, String>() {
//                            @Override
//                            public String load(Integer key) throws Exception {
//                                // 往DB中查询数据
//                                System.out.println("查询key:" + key + "的数据");
//                                return map.get(key);
//                            }
//                        });
        return null;
    }


    /**
     * 内部类
     */
    @Getter
    @Setter
    @ToString
    @EqualsAndHashCode
    @Builder
    private static class User {
        /**
         * 用户名
         */
        private String username;
        /**
         * 年龄
         */
        private Integer age;
        /**
         * 日期
         */
        private Date date;
    }

}
